package mspbots.tsheets.data.core.synclogs;

import com.fasterxml.jackson.databind.JsonNode;
import lombok.RequiredArgsConstructor;
import mspbots.tsheets.data.core.AbstractToolsUtil;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.relational.core.query.Criteria;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

/**
 * mspbots.cw.data.core.synclogs.SyncLogsService
 *
 * @author <a href="https://github.com/vnobo">Alex bob</a>
 * @date Created by 2020/10/19
 */
@Service
@RequiredArgsConstructor
public class SyncLogsServiceImpl extends AbstractToolsUtil {

    public Mono<Page<SyncLogs>> search(Long tenantId, SyncLogsRequest queryParams, Pageable pageable) {

        Criteria criteria = Criteria.from(Criteria.where("tenantId").is(tenantId));
        criteria = criteria.and("time").between(queryParams.getStartTime(), queryParams.getEndTime());
        if (!StringUtils.isEmpty(queryParams.getAction())) {
            criteria = criteria.and("action").is(queryParams.getAction());
        }
        Flux<SyncLogs> contents = this.databaseClient.select().from(SyncLogs.class).matching(criteria)
                .orderBy(pageable.getSort()).page(pageable).fetch().all();

        Mono<Long> count = this.databaseClient.select().from(SyncLogs.class).matching(criteria).fetch().all().count();

        return contents.collectList().zipWith(count).flatMap(objects ->
                Mono.just(new PageImpl<>(objects.getT1(), pageable, objects.getT2())));
    }

    public Flux<SyncLogs> find(Long tenantId, SyncLogsRequest queryParams, Pageable pageable) {
        Criteria criteria = Criteria.from(Criteria.where("tenantId").is(tenantId));
        criteria = criteria.and("time").between(queryParams.getStartTime(), queryParams.getEndTime());
        if (!StringUtils.isEmpty(queryParams.getAction())) {
            criteria = criteria.and("action").is(queryParams.getAction());
        }
        return this.databaseClient.select().from(SyncLogs.class).matching(criteria)
                .orderBy(pageable.getSort()).page(pageable).fetch().all();
    }

    public Mono<JsonNode> count(Long tenantId, SyncLogsRequest queryParams) {

        Criteria criteria = Criteria.from(Criteria.where("tenantId").is(tenantId));
        criteria = criteria.and("time").between(queryParams.getStartTime(), queryParams.getEndTime());
        if (!StringUtils.isEmpty(queryParams.getAction())) {
            criteria = criteria.and("action").is(queryParams.getAction());
        }
        return this.databaseClient.select().from(SyncLogs.class).matching(criteria).fetch().all().count()
                .map(result -> this.objectMapper.createObjectNode().put("result", result));
    }

    public Flux<SyncLogsResponse> stats(Long tenantId) {
        return this.databaseClient.execute("SELECT status,count(*) FROM cw_sync_logs " +
                "WHERE tenant_id=:tenantId GROUP BY status")
                .as(SyncLogsResponse.class)
                .bind("tenantId", tenantId)
                .fetch().all();
    }
}
